#include "piece.h"

namespace gm
{
    Piece::Piece(Tetromino& t, int x0, int y0, int i)
        : tetro_set(t), x(x0), y(y0), index(i)
    {
        if(tetro_set[0][0].first == 'I')
            SRS = &gm::SRS_I;
        else if(tetro_set[0][0].first == 'O')
            SRS = &gm::SRS_O;
        else 
            SRS = &gm::SRS;
        changed_gy();
    }
    Matrix* Piece::p_playField = nullptr;

    void Piece::set_playField(Matrix *p)
    {
        p_playField = p;
    }

    void Piece::down(int dy)
    {
        move(0, -dy);
    }

    void Piece::left()
    {
        move(-1, 0);
        changed_gy();
    }

    void Piece::right()
    {
        move(1, 0);
        changed_gy();
    }

    void Piece::rotate()
    {
        int i = index;
        index = (index + 1) % 4;
        auto srs = *SRS;
        for(int j = 0; j < srs[index].size(); j++)
        {
            auto dx = srs[i][j].first - srs[index][j].first;
            auto dy = srs[i][j].second - srs[index][j].second;
            if(test(x + dx, y + dy))
            {
                x += dx, y += dy;
                changed_gy();
                return;
            }
        }
        index = i;
    }

    std::pair<int, int> Piece::get_mino(int i) const    //获取当前mino的第i个mino形状
    {
        assert(i >= 0 && i <= 3);

        if (i == 0)
            return {0, 0};
        return tetro_set[index][i];
    }

    std::pair<int, int> Piece::get_xy() const //获取当前mino的坐标
    {
        return {x, y};
    }

    int Piece::get_color() const
    {
        return tetro_set[index][0].second;
    }

    int Piece::get_gy() const
    {
        return gy;
    }

    bool Piece::test(int ox, int oy)
    {
        assert(p_playField != nullptr);
        for (int i = 0; i < 4; ++i)
        {
            auto [dx, dy] = get_mino(i);
            if (ox + dx < 0 || ox + dx > (*p_playField).size() - 1 || oy + dy < 0 || oy + dy > (*p_playField)[0].size() - 1)
                return false;
            if ((*p_playField)[ox + dx][oy + dy] > 0)
                return false;
        }
        return true;
    }

    void Piece::move(int dx, int dy)
    {
        if (test(x + dx, y + dy))
        {
            x += dx;
            y += dy;
        }
    }

    void Piece::changed_gy()
    {
        int y = this->y;
        while(test(x, --y));
        y++;
        gy = y;
    }

    Tetromino Piece::get_tetro() const
    {
        return tetro_set;
    }

    void Piece::change_tetro(Tetromino& t)
    {
        tetro_set = t;
    }

}